package com.xpu.stock.service.impl;

import com.google.common.collect.Lists;
import com.xpu.stock.config.vo.StockInfoConfig;
import com.xpu.stock.mapper.StockBusinessMapper;
import com.xpu.stock.mapper.StockMarketIndexInfoMapper;
import com.xpu.stock.mapper.StockRtInfoMapper;
import com.xpu.stock.pojo.StockMarketIndexInfo;
import com.xpu.stock.service.StockTimeTaskService;
import com.xpu.stock.utils.DateTimeUtil;
import com.xpu.stock.utils.IdWorker;
import com.xpu.stock.utils.ParseType;
import com.xpu.stock.utils.ParserStockInfoUtil;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 定义采集股票接口实现
 */
@Service
@Slf4j
public class StockTimeTaskServiceImpl implements StockTimeTaskService {
    @Autowired
    private StockInfoConfig stockInfoConfig;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private StockMarketIndexInfoMapper stockMarketIndexInfoMapper;
    @Autowired
    private StockBusinessMapper stockBusinessMapper;
    @Autowired
    private ParserStockInfoUtil parserStockInfoUtil;
    @Autowired
    private StockRtInfoMapper stockRtInfoMapper;
    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    /**
     * 采集国内大盘,在股票交易日时间范围内调用，时间就能保证正确性
     */
    @Override
    public void collectInnerMarketInfo() {
        //定义采集的url接口
        String url=stockInfoConfig.getMarketUrl()+String.join(",",stockInfoConfig.getInner());
        //调用restTemplate采集数据
        //组装请求头
        HttpHeaders headers = new HttpHeaders();
        headers.add("Referer","https://finance.sina.com.cn/stock/");
        headers.add("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36");
        //组装请求对象
        HttpEntity<Object> entity = new HttpEntity<>(headers);
        //restTemplate发起请求
        String resString = restTemplate.postForObject(url, entity, String.class);
        log.info("当前采集的数据：{}",resString);
        //获取公共采集时间点
        Date curDateTime = DateTimeUtil.getDateTimeWithoutSecond(DateTime.now()).toDate();
        //数据解析（通过正则匹配）
        String reg="var hq_str_(.+)=\"(.+)\";";
        //编译表达式
        Pattern pattern = Pattern.compile(reg);
        //匹配字符串
        Matcher matcher = pattern.matcher(resString);
        ArrayList<StockMarketIndexInfo> infos = new ArrayList<>();
        while (matcher.find()){
            String marketCode = matcher.group(1);
            String otherInfo=matcher.group(2);
            //以逗号切割字符串
            String[] strings = otherInfo.split(",");
            String marketName=strings[0];
            //获取当前大盘点数
            BigDecimal curPoint=new BigDecimal(strings[1]);
            //获取大盘涨跌值
            BigDecimal curPrice=new BigDecimal(strings[2]);
            //
            BigDecimal upDownRate=new BigDecimal(strings[3]);
            //获取成交量
            Long tradeVol=Long.valueOf(strings[4]);
            //
            Long tradeAmount=Long.valueOf(strings[5]);
            StockMarketIndexInfo info = StockMarketIndexInfo.builder().id(idWorker.nextId() + "")
                    .markId(marketCode)
                    .markName(marketName)
                    .currentPrice(curPrice)
                    .curPoint(curPoint)
                    .updownRate(upDownRate)
                    .curTime(curDateTime)
                    .tradeVolume(tradeVol)
                    .tradeAccount(tradeAmount)
                    .build();
             log.info("封装的对象信息：{}",info.toString());
             //收集封装的对象，方便批量插入
            infos.add(info);

        }
       //System.out.println(infos);
        //TODO 批量插入功能
        stockMarketIndexInfoMapper.insetBatch(infos);

    }

    @Override
    public void collectAShareInfo() {
        //获取所有股票code集合（3700+）TODO 后期加入redis缓存
        List<String> stockCodeList = stockBusinessMapper.getAllStockCode();
        //转化集合中股票编码，添加前缀
        stockCodeList=stockCodeList.stream().map(id->{
            if (id.startsWith("6")) {
                id="sh"+id;
            }else {
                id="sz"+id;
            }
            return id;
        }).collect(Collectors.toList());
        //构建好请求头对象
        HttpHeaders headers = new HttpHeaders();
        headers.add("Referer","https://finance.sina.com.cn/stock/");
        headers.add("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36");
        //组装请求对象
        HttpEntity<Object> entity = new HttpEntity<>(headers);
        //将股票集合分片处理，均等分，比如每份20
        /**
         * 参数1：指定被分片的集合
         * 参数2：指定分片后每份集合的元素个数
         * return
         */
        /*Lists.partition(stockCodeList, 20).forEach(list->{
            //为每一份动态拼接url地址，然后通过restTemplate去拉取数据
            String url = stockInfoConfig.getMarketUrl() + String.join(",", list);
            String resultData = restTemplate.postForObject(url, entity, String.class);
            //解析数据，封装pojo
            List stockRtInfos = parserStockInfoUtil.parser4StockOrMarketInfo(resultData, ParseType.ASHSRE);
            log.info("当前解析的集合数据：{}",stockRtInfos);
            //TODO 批量插入
            stockRtInfoMapper.insertBatch(stockRtInfos);

        });*/
        Lists.partition(stockCodeList, 20).forEach(list->{
            //加入线程池后，异步线程处理数据采集，这样提交了操作效率和数据库插入效率（数据库io增加）
            threadPoolTaskExecutor.execute(()->{
                //为每一份动态拼接url地址，然后通过restTemplate去拉取数据
                String url = stockInfoConfig.getMarketUrl() + String.join(",", list);
                String resultData = restTemplate.postForObject(url, entity, String.class);
                //解析数据，封装pojo
                List stockRtInfos = parserStockInfoUtil.parser4StockOrMarketInfo(resultData, ParseType.ASHSRE);
                log.info("当前解析的集合数据：{}",stockRtInfos);
                //TODO 批量插入
                stockRtInfoMapper.insertBatch(stockRtInfos);
            });
        });
    }
}
